package io.renren.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.StringTemplateResourceLoader;
import org.springframework.util.ResourceUtils;

import io.renren.entity.ColumnEntity;
import io.renren.entity.TableEntity;

/**
 * 代码生成器   工具类
 * 
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2016年12月19日 下午11:40:24
 */
/**
 * 代码生成器   工具类
 * 
 */
public class GenUtils {
	
	//换行
	private static String CR = System.getProperty("line.separator");
	private static String userDir = System.getProperty("user.dir");
	/**
	 * 获取默认的代码生成模板
	 * @return
	 */
	private static List<String> getTemplates(){
		List<String> templates = new ArrayList<String>();
		//实体类java bean
		templates.add("classpath:template/Entity.java.btl");
		//dao数据层接口模板
		templates.add("classpath:template/Mapper.java.btl");
		//dao xml模板
		templates.add("classpath:template/Mapper.xml.btl");
		//service 接口模板
		templates.add("classpath:template/Service.java.btl");
		//service实现类模板
		templates.add("classpath:template/ServiceImpl.java.btl");
		//restful controller模板 默认用restful
		templates.add("classpath:template/RestController.java.btl");
//		templates.add("classpath:template/Controller.java.btl");
		return templates;
	}
	
	//读取模板内容
	private static String getTemplate(String classPath){
		String btl="";
		try {
			File file = ResourceUtils.getFile(classPath);
			btl = FileUtils.readFileToString(file, "UTF-8");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return btl;
	}
	
	/**
	 * 生成代码
	 */
	public static void generatorCode(Map<String, String> table, 
			List<Map<String, String>> columns, ZipOutputStream zip){
		//beetl模板引擎配置信息
		Configuration conf = null;
		try {
			conf = Configuration.defaultConfiguration();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		conf.setStatementStart("@");
//		conf.setStatementEnd(null);
		StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
		GroupTemplate gt = new GroupTemplate(resourceLoader, conf);
		
		//获取代码生成器配置
		Properties properties = getProperties();
		
		//表信息
		TableEntity tableEntity = new TableEntity();
		tableEntity.setTableName(table.get("tableName"));
		tableEntity.setComments(table.get("tableComment"));
		//表名转换成Java类名
		String className = tableToJava(tableEntity.getTableName(), properties.getProperty("tablePrefix"));
		tableEntity.setClassName(className);
		tableEntity.setClassname(StringUtils.uncapitalize(className));
		
		//列信息
		List<ColumnEntity> columsList = new ArrayList<>();
		for(Map<String, String> column : columns){
			ColumnEntity columnEntity = new ColumnEntity();
			columnEntity.setColumnName(column.get("columnName"));
			columnEntity.setDataType(column.get("dataType"));
			columnEntity.setComments(column.get("columnComment"));
			columnEntity.setExtra(column.get("extra"));
			
			//列名转换成Java属性名
			String attrName = columnToJava(columnEntity.getColumnName());
			columnEntity.setAttrName(attrName);
			columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
			
			//列的数据类型，转换成Java类型
			String attrType = properties.getProperty(columnEntity.getDataType(), "unknowType");
			columnEntity.setAttrType(attrType);
			
			//是否主键
			if("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() != null){
				tableEntity.setPk(columnEntity);
			}
			
			columsList.add(columnEntity);
		}
		tableEntity.setColumns(columsList);
		
		//没主键，则第一个字段为主键
		if(tableEntity.getPk() == null){
			tableEntity.setPk(tableEntity.getColumns().get(0));
		}
		

		
		//封装模板数据
		Map<String, Object> map = new HashMap<>();
		map.put("tableName", tableEntity.getTableName());
		map.put("comments", tableEntity.getComments());
		map.put("pk", tableEntity.getPk());
		map.put("className", tableEntity.getClassName());
		map.put("classname", tableEntity.getClassname());
		map.put("pathName", tableEntity.getClassname().toLowerCase());
		map.put("columns", tableEntity.getColumns());
		map.put("package", properties.getProperty("package"));
		map.put("author", properties.getProperty("author"));
		map.put("email", properties.getProperty("email"));
		
        
        
        //获取模板列表
		List<String> templates = getTemplates();
		
		for(String template : templates){
			//渲染模板
			String btl = getTemplate(template);
			
			Template beetlTemplate = gt.getTemplate(btl);
			beetlTemplate.binding(map);
			
			String btlCode = beetlTemplate.render();
			
			try {
//				saveSourceFile(getJavaSRCPath(), properties.getProperty("package"), tableEntity.getClassName(), btlCode);
//				添加到zip
//				zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), properties.getProperty("package"))));  
//				IOUtils.write(btl, zip, "UTF-8");
//				zip.closeEntry();
				
				File srcFile  = new File(getFileName(template, tableEntity.getClassName(), properties.getProperty("package")));
				FileUtils.write(srcFile, btlCode, "UTF-8");
				
			} catch (IOException e) {
				throw new RuntimeException("渲染模板失败，表名：" + tableEntity.getTableName(), e);
			}
		}
	}
	
	/**
	 * 
	 * @param srcPath
	 * @param pkg
	 * @param className
	 * @param content
	 * @throws IOException
	 */
	private static  void saveSourceFile(String srcPath,String pkg,String className,String content) throws IOException{
		String file = srcPath+File.separator+pkg.replace('.',File.separatorChar);
		File f  = new File(file);
		f.mkdirs();
		File target = new File(file,className+".java");
		FileWriter writer = new FileWriter(target);
		writer.write(content);;
		writer.close();
	}
	
	//获取java源码目录
	private static String getJavaSRCPath(){
		String srcPath = null;
		if(userDir==null){
			throw new NullPointerException("用户目录未找到");
		}
		File src = new File(userDir,"src");
		File javaSrc = new File(src.toString(),"/main/java");
		if(javaSrc.exists()){
			srcPath = javaSrc.toString();
		}else{
			srcPath = src.toString();
		}		
		return srcPath;
	}
	
	//获取java 资源目录
	private static String getJavaResourcePath(){
		String srcPath = null;
		if(userDir==null){
			throw new NullPointerException("用户目录未找到");
		}
		File src = new File(userDir,"src");
		File resSrc = new File(src.toString(),"/main/resources");
		if(resSrc.exists()){
			srcPath = resSrc.toString();
		}else{
			srcPath = src.toString();
		}		
		return srcPath;
	}
	
	/**
	 * 列名转换成Java属性名
	 */
	public static String columnToJava(String columnName) {
		return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
	}
	
	/**
	 * 表名转换成Java类名
	 */
	public static String tableToJava(String tableName, String tablePrefix) {
		if(StringUtils.isNotBlank(tablePrefix)){
			tableName = tableName.replace(tablePrefix, "");
		}
		return columnToJava(tableName);
	}
	
	/**
	 * 获取代码生成器配置信息
	 */
	private static Properties getProperties(){
		Properties propertie = new Properties();
		try {
			File file = ResourceUtils.getFile("classpath:template/generator.properties");
			propertie.load(FileUtils.openInputStream(file));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		return PropertiesUtil.loadFromFile("classpath:template/generator.properties");
		return propertie;
	}
	
	/**
	 * 获取文件名
	 */
	public static String getFileName(String template, String className, String packageName){
		String packagePath = "";
		if(StringUtils.isNotBlank(packageName)){
			packagePath = getJavaSRCPath()+File.separator+packageName.replace(".", File.separator) + File.separator;
		}
		
		if(template.contains("Entity.java.btl")){
			return packagePath + "entity" + File.separator + className + "Entity.java";
		}
		
		if(template.contains("Mapper.java.btl")){
			return packagePath + "mapper" + File.separator + className + "Mapper.java";
		}
		
		if(template.contains("Mapper.xml.btl")){
//			return packagePath + "dao" + File.separator + className + "Mapper.xml";
			return getJavaResourcePath()+File.separator+"mapper"+File.separator+className+ "Mapper.xml";
		}
		
		if(template.contains("Service.java.btl")){
			return packagePath + "service" + File.separator +"I"+ className + "Service.java";
		}
		
		if(template.contains("ServiceImpl.java.btl")){
			return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
		}
		
		if(template.contains("Controller.java.btl")){
			return packagePath + "controller" + File.separator + className + "Controller.java";
		}
		
		return null;
	}
}
